#include "Fl_Window_Image2OpenGLBox.h"
#include <FL/Fl.h>

namespace FPTK{

void Fl_Window_Image2OpenGLBox::Init()
{
curs=0;
//cursor(FL_CURSOR_DEFAULT, FL_WHITE, FL_BLACK);
activ=0;
    W=0;
    H=0;
    B=0;
    resiz=0;
    x_curs=-1;
    y_curs=-1;
    imagei=NULL;
    drag=0;
    nonmodal=1;
    size_mini_x=Fl::w()/5;
    zone_zoom_x=size_mini_x/2;
    size_mini_y=Fl::h()/5;
    zone_zoom_y=size_mini_y/2;
}


Fl_Window_Image2OpenGLBox::Fl_Window_Image2OpenGLBox(int X, int Y, int W, int H):Fl_Gl_Window(X,Y,W,H)
{
Init();
}

Fl_Window_Image2OpenGLBox::Fl_Window_Image2OpenGLBox(int X, int Y, int W, int H,const char *l):Fl_Gl_Window(X,Y,W,H,l)
{
Init();
}


Fl_Window_Image2OpenGLBox::Fl_Window_Image2OpenGLBox(int W, int H):Fl_Gl_Window(W,H)
{
Init();
}

Fl_Window_Image2OpenGLBox::~Fl_Window_Image2OpenGLBox()
{
if(imagei)
   {
   free(imagei);
   imagei=NULL;
   }
}

void Fl_Window_Image2OpenGLBox::draw()
{
//std::cout<<label()<<std::endl;
//std::cout<<"draw"<<std::endl;
    int window_W=w();
    int window_H=h();
    //std::cout<<window_W<<" "<<window_H<<std::endl;
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
    glClear(GL_COLOR_BUFFER_BIT);
    
    glOrtho(0,window_W,0,window_H,0,1);
    float x=float(window_W)/float(W);
    float y=float(window_H)/float(H);
    if(x>y)
       {
       x=y;//x=y/float(window_H)*float(W);
       }
    else
       {
       y=x;//y=x/float(window_W)*float(H);
       }
    //std::cout<<window_H<<" "<<window_W<<std::endl;
    glPixelZoom(x,y);//float(window_W)/float(W),float(window_H)/float(H));
    glRasterPos2i(0,0);//window_H-int(float(H)*y));

    //glOrtho(0,W,0,H,0,1);
    if(B==1)
       {
       glDrawPixels(W,H,GL_LUMINANCE, GL_UNSIGNED_BYTE, imagei);
       }
    glPixelStorei(GL_UNPACK_ALIGNMENT,1);
    if(B==3)
       {
       glDrawPixels(W,H,GL_RGB, GL_UNSIGNED_BYTE , imagei);
       }
    glPopMatrix();

}

int Fl_Window_Image2OpenGLBox::LoadImage(char *filename)
{
if(imagei)
   {
   //std::cout<<"free"<<std::endl;
   free(imagei);
   imagei=NULL;
   }
//std::ostream& my_cout = std::cout;
	//read the given bmp
//	image_bmp.loadBMP(filename,my_cout);

if(image_bmp.Load(filename)!=1)
   {
   std::cout<<"ERROR ALLOC LOAD IMAGE "<<filename<<std::endl;
   }
//std::cout<<"new"<<std::endl;
H=image_bmp.GetHeight();
W=image_bmp.GetWidth();
B=image_bmp.GetBPP()/8;
//size(W,H);
//std::cout<<H<<" "<<" "<<W<<" "<<B<<std::endl;


   imagei =(GLubyte *) calloc(H*B*W,sizeof(char));
   //memcpy (imagei,image_bmp.GetData(), H*W*B);
   if(imagei)
      {
      memcpy (imagei,image_bmp.GetImg(), H*W*B);
      }
   else
      {
      std::cout<<"error: Not enough memory"<<std::endl;
      }

int screen_H=Fl::h();
//size(screen_W/3,H*screen_W/3/W);
size(W*screen_H/3/H,screen_H/3);
//std::cout<<size_mini_x<<" "<<W*screen_H/3/H<<std::endl;
if(size_mini_x>w())
   {
   size_mini_x=w()*2/3;
   zone_zoom_x=size_mini_x/2;
   }
ResizeWindow();
if(nonmodal && !non_modal())
{
hide();
do_callback();
set_non_modal();
show();
}
//std::cout<<"ok"<<std::endl;
redraw();
return 1;
}

int Fl_Window_Image2OpenGLBox::handle(int event)
{
//std::cout<<curs<<std::endl;
int x_curs_old=x_curs;
int y_curs_old=y_curs;
if(((Fl::event_x()>=w()-zone_zoom_x && Fl::event_y()>=h()-zone_zoom_y) || (resiz && curs==1)) && curs!=1 && visible())
   {
   //std::cout<<"plop1"<<std::endl;
   cursor(FL_CURSOR_NWSE, FL_WHITE, FL_BLACK);
   curs=1;
   }
else if(((Fl::event_x()<=zone_zoom_x && Fl::event_y()>=h()-zone_zoom_y) || (resiz && curs==2)) && curs!=2 && visible())
   {
   //std::cout<<"plop2"<<std::endl;
   cursor(FL_CURSOR_NESW, FL_WHITE, FL_BLACK);
   curs=2;
   }
else if(visible() && curs!=3 && (Fl::event_x()<(w()-zone_zoom_x) || Fl::event_y()<(h()-zone_zoom_y)) 
                 && (Fl::event_x()>zone_zoom_x || Fl::event_y()<(h()-zone_zoom_y)))
   {
   //std::cout<<"plop3"<<std::endl;
   cursor(FL_CURSOR_MOVE, FL_WHITE, FL_BLACK);
   curs=3;
   }
  switch(event)
     {
    case FL_PUSH:
       if(Fl::event_button1())
          {
          curs=0;
          //cursor(FL_CURSOR_WAIT, FL_WHITE, FL_BLACK);
          activ=1;
          x_curs=Fl::event_x_root();
          y_curs=Fl::event_y_root();
          if(Fl::event_clicks()>=1)
             {
             Fl::event_is_click(0);
             if(non_modal())
                {
                set_non_modal();
                nonmodal=1;
                }
             hide();
             do_callback();
             }
          }
       if(Fl::event_button2())
          {
          /*
          curs=0;
          //cursor(FL_CURSOR_WAIT, FL_WHITE, FL_BLACK);
          std::cout<<"non modal"<<non_modal()<<std::endl;
          hide();
          if(!non_modal())
             {
             do_callback();
             }
          set_non_modal();
          if(non_modal())
             {
             nonmodal=1;
             }
          else
             {
             nonmodal=0;
             }
          show();
          std::cout<<"non modal"<<non_modal()<<std::endl;
          */
          }
       if(Fl::event_button3())
          {
          curs=0;
          //cursor(FL_CURSOR_WAIT, FL_WHITE, FL_BLACK);
          ResizeWindow();
           if(!border())
              {
              hide();
              border(true);
              show();
              }
           else
              {
              hide();
              border(false);
              show();
              }
          }
       return 1;
       break;
     case FL_RELEASE:
        activ=0;
        x_curs=-1;
        y_curs=-1;
        drag=0;
        resiz=0;
        return 1;
        break;
     case FL_DRAG:
        if(!activ)
           {
           return 0;
           }
        
        x_curs=Fl::event_x_root();
        y_curs=Fl::event_y_root();
        //x_curs_wind_old=Fl::event_x();
           //y_curs_wind_old=Fl::event_y();
        if(x_curs_old!=-1 && y_curs_old!=-1)
           {
           //std::cout<<x_curs<<" "<<x_curs_old<<"   "<<y_curs<<" "<<y_curs_old<<"..."<<w()<<" "<<h()<<std::endl;
           if((x_curs-x_curs_old!=0 || y_curs-y_curs_old!=0) && x_curs_old!=-1 && y_curs_old!=-1)
              {
              if((Fl::event_x()<(w()-zone_zoom_x) || Fl::event_y()<(h()-zone_zoom_y) || drag==1) && !resiz
                 && (Fl::event_x()>zone_zoom_x || Fl::event_y()<(h()-zone_zoom_y) || drag==1))
                 {
                 position(x()+x_curs-x_curs_old,y()+y_curs-y_curs_old);
                 drag=1;
                 }
              else
                 {
                 //std::cout<<"plop"<<std::endl;
                 if(Fl::event_x()>=(w()-zone_zoom_x) && Fl::event_y()>=(h()-zone_zoom_y))
                    {
                    if(w()+x_curs-x_curs_old>size_mini_x && h()+y_curs-y_curs_old>size_mini_y)
                       {
                       size(w()+x_curs-x_curs_old,h()+y_curs-y_curs_old);
                       resiz=1;
                       ResizeWindow();
                       }
                    }
                 if(Fl::event_x()<=zone_zoom_x && Fl::event_y()>=(h()-zone_zoom_y))
                    {
                    if(w()-x_curs+x_curs_old>size_mini_x && h()+y_curs-y_curs_old>size_mini_y)
                       {
                       //std::cout<<x()+w()<<std::endl;
                       int old_w=w();
                       size(w()-x_curs+x_curs_old,h()+y_curs-y_curs_old);
                       //std::cout<<x()+w()<<std::endl;
                       resiz=1;
                       ResizeWindow();
                       position(x()-w()+old_w,y());
                       }
                    }
                 }
              }
           }
        return 1;
        break;
     default:
        return 0;
        break;
     }
   }


int Fl_Window_Image2OpenGLBox::ResizeWindow()
   {
   /*int window_W=w();
   int window_H=h();
   float x=float(window_W)/float(W);
   float y=float(window_H)/float(H);
   if(x>y)
      {
      x=y;//x=y/float(window_H)*float(W);
      }
   else
      {
      y=x;//y=x/float(window_W)*float(H);
      }
   
   size(W*x,H*y);*/

int window_W=w();
   int window_H=h();
   float x=float(window_W)/float(W);
   float y=float(window_H)/float(H);
   if(x<y)
      {
      x=y;//x=y/float(window_H)*float(W);
      }
   else
      {
      y=x;//y=x/float(window_W)*float(H);
      }
   
   size(W*x,H*y);



   return 0;
   }

}